home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH17 / LATENCY2.ASM < prev    next >
Encoding:
Assembly Source File  |  1994-07-13  |  4.0 KB  |  145 lines

  1. ; This program measures the latency of an INT 01ch ISR.
  2. ; It works by reading the timer chip immediately upon entering
  3. ; the INT 01ch ISR  By averaging this value for some number of
  4. ; executions, we can determine the average latency for this
  5. ; code.
  6.  
  7.         .xlist
  8.         .386
  9.         option        segment:use16
  10.         include     stdlib.a
  11.         includelib    stdlib.lib
  12.         .list
  13.  
  14.  
  15. cseg        segment    para public 'code'
  16.         assume    cs:cseg, ds:nothing
  17.  
  18. ; All the variables are in the code segment in order to reduce ISR
  19. ; latency (we don't have to push and set up DS, saving a few instructions
  20. ; at the beginning of the ISR).
  21.  
  22. OldInt1ch        dword    ?
  23. SumLatency    dword    0
  24. Executions    dword    0
  25. Average        dword    0
  26.  
  27. ; This program reads the 8254 timer chip.  This chip counts from
  28. ; 0FFFFh down to zero and then generates an interrupt.  It wraps
  29. ; around from 0 to 0FFFFh and continues counting down once it
  30. ; generates the interrupt.
  31. ;
  32. ; 8254 Timer Chip port addresses:
  33.  
  34. Timer0_8254    equ    40h
  35. Cntrl_8254    equ    43h
  36.  
  37.  
  38. ; The following ISR reads the 8254 timer chip, negates the result
  39. ; (because the timer counts backwards), adds the result to the
  40. ; SumLatency variable, and then increments the Executions variable
  41. ; that counts the number of times we execute this code.  In the
  42. ; mean time, the main program is busy computing and displaying the
  43. ; average latency time for this ISR.
  44. ;
  45. ; To read the 16 bit 8254 counter value, this code needs to
  46. ; write a zero to the 8254 control port and then read the
  47. ; timer port twice (reads the L.O. then H.O. bytes).  There
  48. ; needs to be a short delay between reading the two bytes
  49. ; from the same port address.
  50.  
  51. TimerISR    proc    near
  52.         push    ax
  53.         mov    eax, 0        ;Ch 0, latch & read data.
  54.         out    Cntrl_8254, al    ;Output to 8253 cmd register.
  55.         in    al, Timer0_8254    ;Read latch #0 (LSB) & ignore.
  56.         mov    ah, al
  57.         jmp    SettleDelay    ;Settling delay for 8254 chip.
  58. SettleDelay:    in    al, Timer0_8254    ;Read latch #0 (MSB)
  59.         xchg    ah, al
  60.         neg    ax        ;Fix, 'cause timer counts down.
  61.         add     cseg:SumLatency, eax
  62.         inc    cseg:Executions
  63.         pop    ax
  64.         jmp    cseg:OldInt1ch
  65. TimerISR    endp
  66.  
  67.  
  68.  
  69. Main        proc
  70.         meminit
  71.  
  72. ; Begin by patching in the address of our ISR into int 1ch's vector.
  73. ; Note that we must turn off the interrupts while actually patching
  74. ; the interrupt vector and we must ensure that interrupts are turned
  75. ; back on afterwards;  hence the cli and sti instructions.  These are
  76. ; required because a timer interrupt could come along between the two
  77. ; instructions that write to the int 1ch interrupt vector.  Since the
  78. ; interrupt vector is in an inconsistent state at that point, this
  79. ; could cause the system to crash.
  80.  
  81.         mov    ax, 0
  82.         mov    es, ax
  83.         mov    ax, es:[1ch*4]
  84.         mov    word ptr OldInt1ch, ax
  85.         mov    ax, es:[1ch*4 + 2]
  86.         mov    word ptr OldInt1ch+2, ax
  87.  
  88.         cli
  89.         mov    word ptr es:[1ch*4], offset TimerISR
  90.         mov    es:[1ch*4 + 2], cs
  91.         sti
  92.  
  93. ; First, wait for the first call to the ISR above.  Since we will be dividing
  94. ; by the value in the Executions variable, we need to make sure that it is
  95. ; greater than zero before we do anything.
  96.  
  97. Wait4Non0:    cmp    cseg:Executions, 0
  98.         je    Wait4Non0
  99.  
  100.  
  101. ; Okay, start displaying the good values until the user presses a key at
  102. ; the keyboard to stop everything:
  103.  
  104. DisplayLp:    mov    eax, SumLatency
  105.         cdq                ;Extends eax->edx.
  106.         div    Executions
  107.         mov     Average, eax
  108.         printf
  109.         byte    "Count: %ld, average: %ld\n",0
  110.         dword    Executions, Average
  111.  
  112.         mov    ah, 1            ;Test for keystroke.
  113.         int    16h
  114.         je    DisplayLp
  115.         mov    ah, 0            ;Read that keystroke.
  116.         int    16h
  117.  
  118.  
  119.  
  120. ; Okay, restore the interrupt vector.  We need the interrupts off
  121. ; here for the same reason as above.
  122.  
  123.         mov    ax, 0
  124.         mov    es, ax
  125.         cli
  126.         mov    ax, word ptr OldInt1ch
  127.         mov    es:[1ch*4], ax
  128.         mov    ax, word ptr OldInt1ch+2
  129.         mov    es:[1ch*4+2], ax
  130.         sti
  131.  
  132. Quit:        ExitPgm            ;DOS macro to quit program.
  133. Main        endp
  134.  
  135. cseg        ends
  136.  
  137. sseg        segment    para stack 'stack'
  138. stk        db    1024 dup ("stack   ")
  139. sseg        ends
  140.  
  141. zzzzzzseg    segment    para public 'zzzzzz'
  142. LastBytes    db    16 dup (?)
  143. zzzzzzseg    ends
  144.         end    Main
  145.